#include <iostream>
#include <string_view>
#include <array>

namespace cpp20 {

// consteval: 编译时求值函数
consteval int square(int n) {
    return n * n;
}

// 常量表达式函数(可以在编译时或运行时求值)
constexpr int cube(int n) {
    return n * n * n;
}

// 使用consteval调用其他consteval函数
consteval int fourth_power(int n) {
    return square(n) * square(1);  // 必须在编译时求值
}

// constinit: 要求变量必须静态/线程局部初始化
constinit thread_local int thread_counter = 0;

// 全局变量使用constinit
constinit int global_value = cube(3);  // 使用constexpr函数初始化

// 不能直接使用consteval函数初始化非constexpr变量，但可以在constexpr变量初始化中使用
constexpr int compile_time_value = square(5);  // OK

// 下面是几个展示consteval必须在编译时求值的例子
struct CompileTimeOnly {
    consteval CompileTimeOnly() = default;
    
    consteval int get_value() const {
        return 42;
    }
};

consteval CompileTimeOnly get_compile_time_object() {
    return CompileTimeOnly{};
}

// 在编译期检测素数的例子
consteval bool is_prime(int n) {
    if (n <= 1) return false;
    if (n <= 3) return true;
    if (n % 2 == 0 || n % 3 == 0) return false;
    
    for (int i = 5; i * i <= n; i += 6) {
        if (n % i == 0 || n % (i + 2) == 0) {
            return false;
        }
    }
    return true;
}

// 在编译期生成素数表
template <int N>
consteval std::array<int, N> generate_primes() {
    std::array<int, N> primes{};
    int count = 0;
    
    for (int i = 2; count < N; ++i) {
        if (is_prime(i)) {
            primes[count++] = i;
        }
    }
    
    return primes;
}

class ConstInitDemo {
private:
    // 类成员变量使用constinit (C++20需要使用static)
    static constinit int s_instance_count;
    
public:
    ConstInitDemo() {
        s_instance_count++;
    }
    
    ~ConstInitDemo() {
        s_instance_count--;
    }
    
    static int get_instance_count() {
        return s_instance_count;
    }
};

// 定义静态成员变量
constinit int ConstInitDemo::s_instance_count = 0;

void demonstrate_consteval_constinit() {
    std::cout << "  C++20 consteval和constinit关键字演示:\n\n";

    // 1. consteval函数演示
    std::cout << "  1. consteval函数演示:\n";
    
    // 使用consteval函数
    constexpr int sq5 = square(5);  // 编译时计算
    // int runtime_sq = square(runtime_value);  // 错误: consteval函数必须在编译时求值
    
    std::cout << "  square(5) = " << sq5 << "\n";
    std::cout << "  fourth_power(3) = " << fourth_power(3) << "\n";
    
    // 编译期素数检测
    std::cout << "  is_prime(17) = " << (is_prime(17) ? "true" : "false") << "\n";
    std::cout << "  is_prime(20) = " << (is_prime(20) ? "true" : "false") << "\n";
    
    // 使用编译期生成的素数表
    constexpr auto first_10_primes = generate_primes<10>();
    std::cout << "  前10个素数: ";
    for (int i = 0; i < 10; ++i) {
        std::cout << first_10_primes[i] << " ";
    }
    std::cout << "\n\n";
    
    // 2. constinit变量演示
    std::cout << "  2. constinit变量演示:\n";
    std::cout << "  全局变量global_value = " << global_value << "\n";
    
    // 修改thread_local变量
    thread_counter++;
    std::cout << "  线程本地变量thread_counter = " << thread_counter << "\n";
    
    // 使用带有constinit静态成员的类
    ConstInitDemo obj1, obj2, obj3;
    std::cout << "  创建三个ConstInitDemo对象后的实例计数: " 
              << ConstInitDemo::get_instance_count() << "\n\n";
    
    // 3. consteval vs constexpr对比
    std::cout << "  3. consteval vs constexpr对比:\n";
    
    constexpr int compile_time_cube = cube(4);  // 编译时计算
    int runtime_value = 5;
    int runtime_cube = cube(runtime_value);     // 运行时计算
    
    std::cout << "  constexpr cube(4) = " << compile_time_cube << "\n";
    std::cout << "  运行时 cube(" << runtime_value << ") = " << runtime_cube << "\n\n";
    
    // 4. 优势与适用场景
    std::cout << "  C++20 consteval和constinit的优势:\n\n";
    
    std::cout << "  consteval的优势:\n";
    std::cout << "  • 保证函数只能在编译时求值，增强代码正确性\n";
    std::cout << "  • 避免意外的运行时开销\n";
    std::cout << "  • 相比constexpr，提供更强的编译时保证\n";
    std::cout << "  • 适用于需要纯编译期行为的场景，如模板元编程\n\n";
    
    std::cout << "  constinit的优势:\n";
    std::cout << "  • 确保静态/线程局部变量使用常量初始化\n";
    std::cout << "  • 避免静态初始化顺序问题 (Static Initialization Order Fiasco)\n";
    std::cout << "  • 提高程序启动性能\n";
    std::cout << "  • 与constexpr和const不同，变量在初始化后可以修改\n";
}

} // namespace cpp20 